/**
 * ***************************************
 * @file circular_queue.h
 * @author: AnRui
 * @version 0.1
 * @date  : 2025-06-20
 * @copyright Copyright (c) 2025
 * @desc: 队列是一种数据结构,特点是先进先出
 *        想要实现这个特点 队列必须包含几个信息
 *          1.保存队列数据的暂存区(数组) buffer
 *          2.队列的长度size,暂存区(数组)长度
 *          3.队列的头head (数组下标), 保存有效数据的开始位置
 *          4.队列的尾tail (数组下标), 保存下一个要放入数据的位置
 *          5.队列当前数据量curNum
 *        队列的几种状态:
 *          1.初始态: 指定队列暂存区位置和长度,头尾初始化为0,当前数据量=0。
 *          2.队列压入数据:   buffer[tail]=值 , tail+1,curNum+1
 *          3.队列弹出数据:   值=buffer[head] , head+1,curNum-1
 *          4.队列为空状态:   curNum=0
 *          5.队列为满的状态: curNum=size
 *        特殊说明:
 *          为什么要%size
 *             % size（取模运算）的作用是让索引在达到数组最大长度时 “循环回到” 数组起始位置,从而实现环形缓冲区的效果。
 *            例如：
 *               数组长度size=5，索引范围是0~4。
 *               当tail移动到索引4（数组末尾）时，下一次移动应回到索引0
 * ***************************************
 */

#ifndef __QUEUE_H__
#define __QUEUE_H__
#include "gd32f30x.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h> 

 /*****************************Struct|Enum******************************** */
typedef struct {
    uint32_t head;        //数组下标，指向队头
    uint32_t tail;        //数组下标，指向队尾
    uint32_t size;        //队列缓存长度（初始化时赋值）
    uint8_t* buffer;      //队列缓存数组（初始化时赋值）
    uint32_t curNum;      //队列当前的数据个数
} QueueStruct;

typedef enum {
    QUEUE_OK = 0,       //队列正常
    QUEUE_ERROR,        //队列错误
    QUEUE_OVERLOAD,     //队列已满
    QUEUE_EMPTY,        //队列已空
    QUEUE_OVERSIZE,     //插入的数据个数超出队列长度
    QUEUE_OVERNUM,      //取出的数据个数超出队列当前的数据量
} QueueStatusEnum;

/**************************Function*********************************** */
/**
 * @desc  : 初始化队列
 * @date  : 2025-03-26
 * @author: AnRui
 * @param : queue - {参数说明}: 队列
 * @param : buffer - {参数说明}: 队列缓冲区地址
 * @param : size - {参数说明}: 队列缓冲区长度
 * @note  :
 */
QueueStatusEnum QueueInit(QueueStruct* queue, uint8_t* buffer, uint32_t size);


/**
 * @desc  : 向队列中压入数据
 * @date  : 2025-03-26
 * @author: AnRui
 * @param : queue - {参数说明}: 队列指针
 * @param : data - {参数说明}: 待压入的数据
 * @return: 队列的操作状态码
 * @note  :
 */
QueueStatusEnum QueuePush(QueueStruct* queue, uint8_t data);



/**
 * @desc  : 从队列中弹出数据
 * @date  : 2025-03-26
 * @author: AnRui
 * @param : queue - {参数说明}: 队列指针
 * @param : data - {参数说明}:  数据指针
 * @return: 队列的操作状态码
 * @note  :
 */
QueueStatusEnum QueuePop(QueueStruct* queue, uint8_t* data);




/**
 * @desc  : 向队列中压入一组数据
 * @date  : 2025-03-26
 * @author: AnRui
 * @param : queue - {参数说明}: 队列指针
 * @param : dataArr - {参数说明}: 要压入的数据数组指针
 * @param : len - {参数说明}: 需要压入数据的长度
 * @return: 队列的操作状态码
 * @note  :
 */
QueueStatusEnum QueuePushArr(QueueStruct* queue, uint8_t* dataArr, uint32_t len);


/**
 * @desc  : 从队里中弹出一组数组
 * @date  : 2025-03-26
 * @author: AnRui
 * @param : queue - {参数说明}:队列指针
 * @param : dataArr - {参数说明}:待弹出队列的数据缓存地址
 * @param : len - {参数说明}:len, 待弹出队列的数据的最大长度
 * @return: 队列的操作状态码
 * @note  :
 */
QueueStatusEnum QueuePopArr(QueueStruct* queue, uint8_t* dataArr, uint32_t len);





/**
 * @desc  : 清空队列
 * @date  : 2025-06-20
 * @author: AnRui
 * @param : queue - {参数说明}: 队列指针
 * @note  :
 */
QueueStatusEnum QueueClear(QueueStruct* queue);







/**
 * @desc  : 获取队列中有效数据的个数
 * @date  : 2025-03-26
 * @author: AnRui
 * @param : queue - {参数说明}: 队列
 * @return: 队列中数据的个数
 * @note  :
 */
QueueStatusEnum GetQueueDataNum(QueueStruct* queue, uint32_t* num);



#endif
